<?php
/**
 * Zead
 *
 * LICENSE	
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/bsd-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to eu@marcelomx.com so we can send you a copy immediately.
 *
 * @category   Zead
 * @author     Marcelo Rodrigues Gonzaga <eu@marcelomx.com>
 * @copyright  Copyright (c) 2008 Marcelo Rodrigues Gonzaga
 * @link       http://code.google.com/p/zead 
 * @license    http://www.opensource.org/licenses/bsd-license.php     New BSD License
 *
 **/
 

/** Zend_Auth_Adapter_Interface */
require_once 'Zend/Auth/Adapter/Interface.php';

/** Zend_Session **/
require_once 'Zend/Session.php';

/**
 * Class Zead_Auth_Adapter_Session 
 * 
 * @category   Zead
 * @package    Zead_Auth
 * @subpackage Zead_Auth_Adapter
 * @copyright  Copyright (c) 2008 Marcelo Rodrigues Gonzaga 
 * @license    http://www.opensource.org/licenses/bsd-license.php     New BSD License 
 */
class Zead_Auth_Adapter_Session implements Zend_Auth_Adapter_Interface 
{
	/**
	 * Os indices padres utilizados comom dados na credencial de autenticacao
	 */
	const CREDENTIAL_DEFAULT_KEYS = 'basePath,fileName,ip,browser,time';

	/**
	 * O diretrio padro onde ser salvo o arquivo que guarda os dados do processo.
	 * O padro  um diretrio temporrio.
	 * @var string
	 */
	protected $_baseDir = null;
	
	/**
	 * A string contendo o id do processo a ser validado.
	 * @var string
	 */
	protected $_identity = null;

	/**
	 * Os dados da credencial associados a identidade
	 * @var array
	 */
	protected $_credential = array();
	
	/**
	 * O objeto que contem o resultado do processo.
	 * @var Zend_Auth_Result
	 */
	protected $_result = null;

	/**
	 * Status atual para autenticacao. Somente utilizado aps a primeira validao.
	 * @var bool
	 */
	protected $_locked = false;
	
	/**
	 * Seta o identificador do processo.
	 * @param string $identity
	 */
	public function setIdentity($identity) 
	{
		$this->_identity = $identity;
		
		return $this;
	}
	
	/**
	 * Retorna o identificador da sesso
	 * @return string
	 */
	public function getIdentity()
	{
		return $this->_identity;
	}

	/**
	 * Seta os dados credenciais associados ao identificador
	 * para validao de acesso.
	 *
	 * @param array $credential
	 */ 
	public function setCredential(array $credential = array()) 
	{
		$this->_credential = $credential;
	
		return $this;
	}

	/**
	 * Retorna os dados credenciais associados a esse identificador
	 * 
	 * @return array
	 */
	public function getCredential() 
	{
		return $this->_credential;
	}

	/**
	 * Retorna os dados da credencial normalizados
	 * @return array
	 */
	public function getCredentialNormalized() 
	{
		$credential = array();
		foreach ($this->_credential as $param => $value) {
			if ($param == 'browser' || $param == 'basePath')
				$credential[$param] = base64_decode($value);
			else
				$credential[$param] = $value;
		}

		return $credential;
	}

	/**
	 * Seta o objeto de requisicao HTTP
	 * @param Zend_Controller_Request_Abstract
	 */
	public function setRequest(Zend_Controller_Request_Abstract $request)
	{
		$this->_request = $request;
		return $this;
	}

	/**
 	 * Retorna o objeto de requisicao HTTP
	 * @return Zend_Controller_Request_Abstract
	 */
	public function getRequest()
	{
		return $this->_request;
	}
	
	/**
	 * Altera o valor do diretrio onde sero salvos os dados do processo
	 * @param string
	 */
	public function setBaseDir($baseDir = null) 
	{
		if (!is_dir($baseDir))
			return;
			
		$this->_baseDir = $baseDir;
		
		return $this;
	}
	
	/**
	 * Retorna o diretrio onde sero salvos os dados do processo.
	 * Se for nulo, seta o variavel de ambiente contendo o TMP do sistema
	 * operacional.
	 *
	 * @return string
	 */
	public function getBaseDir() 
	{
		if (null == $this->baseDir) {
			$this->setBaseDir($_ENV['TMP']);
		}
		
		return $this->_baseDir;
	}
	
	/**
	 * Autentica o processo e retorna o objeto result, contendo as mensagens
	 * e o codigo do resultado da validacao.
	 * @return Zend_Auth_Result
	 */
	public function authenticate() 
	{				
		// Se no o identificador  nulo ou string vazia
		if (null == $this->_identity || trim($this->_identity) == '') {
			$this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, '');
			
		// Se o arquivo onde sero armazenados os dados de autenticacao existe
		} else if (!file_exists($this->getFileName())) {
			$this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, '');
			
		} else {
			// Validando os dados registrados para a identidade atual
			$credential = unserialize(file_get_contents($this->getFileName()));
			
			if (!sizeof($this->_credential) || !sizeof($credential) || $credential !== $this->_credential) {
				$this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, '');
			} else {
				$this->setCredential($credential);
				$this->_result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_credential);
			}
		}
		
		return $this->_result;
	}

	/**
	 * Retorna o nome do arquivo para onde a identidade serah gravada.
	 * Somente funcionarah caso a identidade seja valida.
	 *
	 * @return string
	 */
	public function getFileName() 
	{
		return $this->getBaseDir() . DIRECTORY_SEPARATOR . $this->_identity . '.txt';
	}
	
	/**
	 * Gera um novo arquivo para a identidade atual. Somente se o resultado
	 * contiver erro 0 (zero)
	 * @return bool
	 */
	public function generateCredential() 
	{
		if (null !== $this->_result && $this->_result->getCode() > 0)
			return $this;
		
		/** @see Zead/Player/Request **/
		require_once 'Zead/Player/Request.php';
		$request = new Zead_Player_Request();

		$credential = array(
			'basePath'  => base64_encode($request->getBasePath()),
			'fileName' => $request->getFileName(),
			'ip'       => $request->getServer('REMOTE_ADDR'),
			'browser'  => base64_encode(($request->getServer('HTTP_USER_AGENT'))),
			'time'     => time(),
			'baseUri'  => dirname($request->getRequestUri())
		);
		
		// Salvando a credencial gerada
		$this->_saveCredential($credential);

		return $credential;
	}

	/**
	 * Salva os dados de credencial para a identidade atual
	 * @param array $credential
	 */ 
	protected function _saveCredential(array $credential = array()) 
	{
		file_put_contents($this->getFileName(), serialize($credential));
	}


	/**
	 * Validando uma credencial
	 * @param array $credential
	 * @return bool
	 */
	protected function _validateCredential(array $credential = array()) 
	{		
		foreach ($credential as $key => $value)
			if (!in_array($key, explode(',', self::CREDENTIAL_DEFAULT_KEYS)))
				return false;
			else if ($value == '')
				return false;

		return true;
	}
}
